﻿/************************************************************************

   Extended Silverlight Toolkit

   Copyright (C) 2010-2012 Xceed Software Inc.

   This program is provided to you under the terms of the Microsoft Public
   License (Ms-PL) as published at http://extendedsilverlight.codeplex.com/license

   Please purchase a commercial version of this toolkit if you are using
   it in a commercial product. The commercial versions support the project,
   and also include more features for each control, priority support,
   source code, updates, removed watermark, and a proprietary license.

   Visit http://xceed.com and follow @datagrid on Twitter.

  **********************************************************************/

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Diagnostics;
using System.Reflection;
using System.Collections.Generic;

namespace Xceed.Silverlight.DataGrid.Utils
{
  public static class TraceHelper
  {
 #if DEBUG && !TRACE_DISABLED
    private static readonly string DefaultFormat = "[{0}]: {1}";
    private static readonly string HeaderFormat = "{0}.{1}";
 #endif

    static TraceHelper()
    {
      TraceHelper.GlobalTraceLevel = DebugTraceLevel.None;
      TraceHelper.TraceHeaderWidth = -1;
    }

    public static DebugTraceLevel GlobalTraceLevel
    {
      get;
      set;
    }

    public static int TraceHeaderWidth
    {
      get;
      set;
    }

    public static void SetTraceLevelForType( Type type, DebugTraceLevel level )
    {
      TraceHelper.TraceLevels.Add( type, level );
    }

    public static IDisposable OverrideTraceLevel( DebugTraceLevel level )
    {
      TraceOverrides.Push( level );

      return new TraceHelperDisposableHelper();
    }

    //Base method, uses object.ToString to get appropriate trace 
    public static void OutputDebugTrace( DebugTraceLevel traceLevel, object trace )
    {
      TraceHelper.OutputDebugTrace( traceLevel, trace.ToString() );
    }

    private static void OutputDebugTrace( DebugTraceLevel traceLevel, string trace )
    {
#if !DEBUG || TRACE_DISABLED
  return;
#else
      StackTrace stackTrace = new StackTrace();
      StackFrame stackFrame = stackTrace.GetFrame( 2 );

      MethodBase callingMethod = stackFrame.GetMethod();

      DebugTraceLevel actualTraceLevel = DebugTraceLevel.None; //default for disabled trace

      if( !TraceHelper.TraceLevels.TryGetValue( callingMethod.DeclaringType, out actualTraceLevel ) )
      {
        actualTraceLevel = TraceHelper.GlobalTraceLevel;
      }

      if( TraceHelper.TraceOverrides.Count > 0 )
      {
        actualTraceLevel = TraceOverrides.Peek();
      }

      if( traceLevel <= actualTraceLevel )
      {
        string className = callingMethod.DeclaringType.Name;
        string methodName = callingMethod.Name;
        string header = string.Format( TraceHelper.HeaderFormat, className, methodName );

        int headerLength = TraceHelper.TraceHeaderWidth;

        if( headerLength > 0 )
        {
          header = header.Substring( header.Length - headerLength );
        }
        else if( headerLength == 0 )
        {
          header = string.Empty;
        }

        string outputString = string.Format( TraceHelper.DefaultFormat, header, trace );

        Debug.WriteLine( outputString );
      }
#endif
    }

    public static void OutputDebugTrace( DebugTraceLevel traceLevel, string format, params object[] paramList )
    {
      string outputString = string.Format( format, paramList );

      TraceHelper.OutputDebugTrace( traceLevel, outputString );
    }

    private static Stack<DebugTraceLevel> TraceOverrides = new Stack<DebugTraceLevel>();
    private static Dictionary<Type, DebugTraceLevel> TraceLevels = new Dictionary<Type, DebugTraceLevel>();

    private class TraceHelperDisposableHelper : IDisposable
    {
      #region IDisposable Members

      void IDisposable.Dispose()
      {
        TraceHelper.TraceOverrides.Pop();
      }

      #endregion
    }

  }

  public enum DebugTraceLevel
  {
    None = -1,
    Info = 0,
    Warning = 1,
    Error = 2,
    Debug = 3,
  }
}
